'''
Created on Apr 20, 2012

@author: root
'''

# All Operations relating to the Hadoop Storage
# Leverages Filesystem, Disk, and Node Object
from Base import Base
import threading
import Queue


class StorageOps(Base):
   
    Users = []
    Nodes = [] 
    Disks = []
    returnQueue2 = Queue.Queue()


#    def IdentifyDevices(self,host):
#        
#        devices = []
#        identifyCMD = "cat /proc/partitions"
#        (status,results) = self.SSHExec(identifyCMD,host,self.installUser,self.installPW)
#        #(hostName,username,status,results) = self.returnQueue.get()
#        lineNum = 0
#        if (status == 0):
#            for deviceInfo in results:
#                if (lineNum > 1):
#                    deviceDetails = deviceInfo.split()
#                    devices.append(deviceDetails[3])
#                lineNum += 1
#                return devices
#
#        else:
#            return devices

    def RemovePartitions(self):
        print "Remove Partitions"
    
    
    
    def Partition(self):
     
        verifyStatus = 0
        hostDiskInfo = []
        partStatus = 0
        preStatus =0
        partExists  = 0
        self.LogInfo("Checking for Existing Partitions")
        print "    * Checking Disk Partitioning"
        threadCount = 0
        Threads = []
        for node in self.Nodes:
            for disk in node.Disks:
                Threads.append(threading.Thread(target=self.__Verify,args=(node.hostName,disk.deviceName)))
                Threads[threadCount].daemon=True
                Threads[threadCount].start()
                threadCount = threadCount + 1
        for thread in Threads:
            thread.join()
            (hostName,deviceName,returnCode) = self.returnQueue2.get()
            if (returnCode == 1 ):
                self.LogError("Partition Already Exists on  "+ str(hostName)+" : "+str(deviceName))
                print "        * ERROR: "+str(hostName)+" : "+str(deviceName)+" Already contains a Partition"
                partStatus =-1 
                preStatus = 0
            elif (returnCode == 2 ):
                self.LogInfo("Pre-Existing Partition Verified on "+ str(hostName)+" : "+str(deviceName))
                print "        * Using "+str(deviceName)+" on "+ str(hostName)
                preStatus += 1
            elif (returnCode == 0 ):
                self.LogInfo("No Partitions on "+ str(hostName)+" : "+str(deviceName))
                print "        * No Partitions on "+ str(hostName)+" : "+str(deviceName)
                preStatus = 0
            elif (returnCode ==3):
                self.LogError("Partition Specified, but No Partitions Exist")
                print "        * ERROR: Partition Specified, but No Partitions Exist on "+ str(hostName)+" : "+str(deviceName)
                partExists = 1
                preStatus = 0
           # verifyStatus += partStatus
            
        if (partStatus < 0):
            self.LogError("Disk Partitions Exist, but were not specified")
            print "---------------------------------------------------"
            print "ERROR: Disk Partitions Exist, but were not specified  "
            print "---------------------------------------------------"
            return -1
        elif (preStatus == threadCount):
            self.LogInfo("Install will use the Pre-Existing Partitions")
            print  "    * Install will use the Pre-Existing Partitions"
            return 0
        elif (partStatus==0) and (preStatus == 0) and (partExists == 0):
            self.LogInfo("Non-Partitioned Disks Verified")
            print  "    * Non-Partitioned Disks Verified"
        elif (partExists == 1):
            self.LogError("Disk Partitions were Specified, but do not exist")
            print "---------------------------------------------------"
            print "ERROR: Disk Partitions were Specified, but do not exist "
            print "---------------------------------------------------"
            return -1
        else:
            self.LogError("Unknown Status")
            print "---------------------------------------------------"
            print "    Unknown Disk Partition Status "
            print "---------------------------------------------------"
            
            return -1

        ''' Partition Status Determined.... Now Let's create partitions if needed'''
        '''  Create a command file to partiton disk, leverage sfdisk and then remove the file '''

        
        threadCount = 0
        Threads = []
        self.LogInfo("Beginning Disk Partitioning")
        print "    * Partitioning Disk Drives on All Cluster Hosts"
        for node in self.Nodes:
            for disk in node.Disks:
                partCMD = str(self.installSudo) + "echo '0,-' > /tmp/"+node.hostName+str(threadCount)+".dat;"+ str(self.installSudo) + "/sbin/sfdisk " + disk.deviceName + " < /tmp/"+node.hostName+str(threadCount)+".dat;rm /tmp/"+node.hostName+str(threadCount)+".dat"
                self.LogInfo(partCMD)
                Threads.append(threading.Thread(target=self.SSHExec,args=(partCMD,node.hostName,self.installUser,self.installPW)))
                Threads[threadCount].daemon=True
                Threads[threadCount].start()
                threadCount = threadCount + 1
        for thread in Threads:
            thread.join()
            (hostName,username,status,results) = self.returnQueue.get()
            self.LogInfo(results)
            currentDevice = (str(results).split()[2])[:-1]
            if (status == 1):
                self.LogError("Error Creating Partition on "+ str(hostName)+" : "+currentDevice)
                print "        * ERROR: Could not create partition on "+ str(hostName)+" : "+currentDevice
            else:
                 newPart = (str(results).split())[36].strip("'")
                 self.LogInfo("Partition Created on  "+ str(hostName)+" : "+str(newPart))
                 print "        * "+str(newPart)+" created on " + str(hostName)
                 hostPartition = {}
                 hostPartition['hostname'] = str(hostName)
                 hostPartition['partition'] = str(newPart)
                 hostPartition['devicename'] = currentDevice
                 hostDiskInfo.append(hostPartition)
          
        ''' Make Changes to the Disk Object with new partition Info '''
              
        for node in self.Nodes:
            for disk in node.Disks:
                for host in hostDiskInfo:
                     if (str(node.hostName) == str(host['hostname'])):
                        if (str(disk.deviceName) == str(host['devicename'])):
                            disk.deviceName = host['partition']
                            disk.partition = 1
                            break  
        
        
        ''' Final Verification '''
          
        verifyStatus = 0
        self.returnQueue2.queue.clear()
        print "    * Verifying Partition Creation"
        threadCount = 0
        Threads = []
        for node in self.Nodes:
            for disk in node.Disks:
                Threads.append(threading.Thread(target=self.__Verify,args=(node.hostName,disk.deviceName)))
                Threads[threadCount].daemon=True
                Threads[threadCount].start()
                threadCount = threadCount + 1
        for thread in Threads:
            thread.join()
            (hostName,deviceName,returnCode) = self.returnQueue2.get()
            if (returnCode!=2):
                verifyStatus = -1
                self.LogError("Could Not Verify Partition on  "+ str(hostName)+" : "+str(deviceName))
                print "        * ERROR: Could Not Verify Partition on  "+ str(hostName)+" : "+str(deviceName)
            else:
                self.LogInfo("Partition Verified on  "+ str(hostName)+" : "+str(deviceName))
                print "        * Partition Verified on  "+ str(hostName)+" : "+str(deviceName)
                
        if (verifyStatus == 0):
            self.LogInfo("All Partitions Verified")       
            return 0

        else:
            self.LogError("All Partitions not created correctly.")
            print "---------------------------------------------------"
            print "ERROR: Disk Partitions Not Created Correctly "
            print "---------------------------------------------------"
            return -1
       
                            
              
        

   


        
        
    def __Verify(self,hostName,deviceName):
        
        verifyCMD = str(self.installSudo) + "/sbin/sfdisk -l " + deviceName
        self.LogInfo(verifyCMD)
        self.SSHExec(verifyCMD,hostName,self.installUser,self.installPW,True)
        (hostName,username,status,results) = self.returnQueue.get()
        if (len(results) > 2) and (status == 0):
            self.returnQueue2.put((hostName,deviceName,1))
        elif (status==1) and ("looks like a partition" in str(results)):
            self.returnQueue2.put((hostName,deviceName,2))
        elif str(deviceName)[-1].isdigit():
            self.returnQueue2.put((hostName,deviceName,3))
        else:  
            self.returnQueue2.put((hostName,deviceName,0))

                

    def __init__(self,Nodes,Users):
       self.Users = Users
       self.Nodes = Nodes
       Base.__init__(self)
       self.SetUsers(self.Users)
        